package com.zhp.dao.base;

import com.zhp.annotation.MyField;
import com.zhp.annotation.MyTable;
import com.zhp.model.Conference;
import com.zhp.utils.JDBCUtil;
import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.GenerousBeanProcessor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class BaseDao<T> {

    private final Class<T> aClass;
    private final String tableNmae;
    private final String ketName;

    public BaseDao(Class<T> aClass) {
        this.aClass = aClass;
        MyTable annotation = aClass.getDeclaredAnnotation(MyTable.class);
        if (null != annotation) {
            tableNmae = annotation.valuee();
            ketName = annotation.key();
        } else {
            tableNmae = "tb";
            ketName = "id";
        }
    }

    public List<T> findByT(Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        sb.append("select * from " + tableNmae + " where ");
        if (map == null || map.isEmpty()) {
            sb.delete(sb.lastIndexOf("where"), sb.length());
        } else {
            Set<String> keySet = map.keySet();
            for (String key : keySet) {
                sb.append(key).append("='").append(map.get(key)).append("' or ");
            }
            sb.delete(sb.lastIndexOf("or"), sb.length());
        }
        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
        List<T> list = new ArrayList<>();
        try {
            BasicRowProcessor processor = new BasicRowProcessor(new GenerousBeanProcessor());
            list = queryRunner.query(sb.toString(), new BeanListHandler<>(aClass, processor));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

    public List<T> findByTAnd(Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        sb.append("select * from " + tableNmae + " where ");
        if (map == null || map.isEmpty()) {
            sb.delete(sb.lastIndexOf("where"), sb.length());
        } else {
            Set<String> keySet = map.keySet();
            for (String key : keySet) {
                sb.append(key).append("='").append(map.get(key)).append("' and ");
            }
            sb.delete(sb.lastIndexOf("and"), sb.length());
        }
        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
        List<T> list = new ArrayList<>();
        try {
            BasicRowProcessor processor = new BasicRowProcessor(new GenerousBeanProcessor());
            list = queryRunner.query(sb.toString(), new BeanListHandler<>(aClass, processor));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

    public int save(T obj) {
        int row = 0;
        StringBuilder sb = new StringBuilder();
        sb.append("INSERT INTO ").append(tableNmae).append(" VALUES(");
        Class<?> aClass = obj.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            if (i == fields.length - 1) {
                sb.append("?)");
            } else {
                sb.append("?,");
            }
        }
        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
        try {
            Object[] params = new Object[fields.length];
//            List<Object> list = new ArrayList<>();
            for (int i = 0; i < fields.length; i++) {
                String fieldName = fields[i].getName();
                String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                Method method = aClass.getDeclaredMethod(methodName);
                Object value = method.invoke(obj);
                params[i] = value;
//                list.add(value);
            }
            row = queryRunner.update(sb.toString(), params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return row;
    }

//    public Conference saveToT(T obj) {
//        Conference conference = null;
//        StringBuilder sb = new StringBuilder();
//        sb.append("INSERT INTO ").append(tableNmae).append(" VALUES(");
//        Class<?> aClass = obj.getClass();
//        Field[] fields = aClass.getDeclaredFields();
//        for (int i = 0; i < fields.length; i++) {
//            if (i == fields.length - 1) {
//                sb.append("?)");
//            } else {
//                sb.append("?,");
//            }
//        }
//        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
//        try {
//            Object[] params = new Object[fields.length];
////            List<Object> list = new ArrayList<>();
//            for (int i = 0; i < fields.length; i++) {
//                String fieldName = fields[i].getName();
//                String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
//                Method method = aClass.getDeclaredMethod(methodName);
//                Object value = method.invoke(obj);
//                params[i] = value;
////                list.add(value);
//            }
//            BasicRowProcessor processor = new BasicRowProcessor(new GenerousBeanProcessor());
//            int update = queryRunner.update(sb.toString(), params);
//            return conference;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    public int update(Object obj) {
        int row = 0;
        StringBuilder sb = new StringBuilder();
        sb.append("update ").append(tableNmae).append(" set ");
        Class<?> aClass = obj.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            MyField myField = field.getAnnotation(MyField.class);
            if (myField == null) {
                sb.append(field.getName()).append("=?,");
            } else {
                sb.append(myField.value()).append("=?,");
            }
        }
        sb.delete(sb.lastIndexOf(","), sb.length());
        sb.append(" where ").append(ketName).append(" = ?");
        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
        try {
            Object[] params = new Object[fields.length + 1];
            for (int i = 0; i < fields.length; i++) {
                String fieldName = fields[i].getName();
                String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                Method method = aClass.getDeclaredMethod(methodName);
                Object value = method.invoke(obj);
                params[i] = value;
                MyField myField = fields[i].getAnnotation(MyField.class);
                if (myField != null) {
                    if (myField.value().equals(ketName)) {
                        //这个是设置最后一个问号
                        params[params.length - 1] = value;
                    }
                } else if (fieldName.equals(ketName)) {
                    params[params.length - 1] = value;
                }
            }
            row = queryRunner.update(sb.toString(),params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return row;
    }

    public Map<String, Object> getUserInfoId(String id) {

        Map<String, Object> map = null;
        String sql = "SELECT d.`name` as dept_name,u.*,ui.*,(SELECT count(*) as total from user_focus where user_id = ? ) as total_focus\n" +
                "from user u \n" +
                "LEFT join user_info ui on  ui.user_id= u.id\n" +
                "LEFT join dept d on d.id = u.dept_id\n" +
                "where u.id = ?";
        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
        try {
            map = queryRunner.query(sql, new MapHandler(), id, id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public T findById(int id) {
        String sql = "select * from " + tableNmae + " where " + ketName + " = " + id;
        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
        try {
            BasicRowProcessor processor = new BasicRowProcessor(new GenerousBeanProcessor());
            return queryRunner.query(sql, new BeanHandler<>(aClass, processor));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    public T findById(String id) {
        String sql = "select * from " + tableNmae + " where " + ketName + " = " + id;
        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
        try {
            BasicRowProcessor processor = new BasicRowProcessor(new GenerousBeanProcessor());
            return queryRunner.query(sql, new BeanHandler<>(aClass, processor));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public int deleteById(Object id) {
        String sql = "delete from " + tableNmae + " where " + ketName + " =?";
        int row = 0;
        QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
        try {
            row = queryRunner.update(sql, id);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return row;
    }

    public T UpdateById(T obj){

        return obj;
    }
}
